﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System.IO;
using Microsoft.Xna.Framework;
using RawLevelFormat;

namespace theguineasyndrome.editor.forms
{
    public partial class EditorForm : Form
    {
        public ContentManager Content;
        private EditorMode editorMode;
        private LevelElementNode currentNode;
        private string tgsDir;
        private string backUpDir;

        public ImageList ImageList
        {
            get { return resourcesView.ImageList; }
        }

        public EditorForm(ContentManager Content, EditorMode editorMode)
        {
            InitializeComponent();

            this.Content = Content;
            this.editorMode = editorMode;

            currentNode = null;
            resourcesView.ImageList = new ImageList();
            ImageList.ImageSize = new Size(32, 32);
            loadResources();

            string home = Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%");
            tgsDir = home + "\\the_guinea_syndrome";

            if (!Directory.Exists(tgsDir))
                Directory.CreateDirectory(tgsDir);

            backUpDir = tgsDir + "\\backup";

            if (!Directory.Exists(backUpDir))
                Directory.CreateDirectory(backUpDir);
        }

        private int addImage(string image)
        {
            Texture2D texture = Content.Load<Texture2D>(image);
            texture.Name = image;
            ImageList.Images.Add(image, Utils.ImageConverter.fromTexture2D(texture));
            return ImageList.Images.IndexOfKey(image);
        }

        public string getTabName()
        {
            return editorTabs.SelectedTab.Text;
        }

        private void loadResources()
        {
            TreeNode Backgrounds = resourcesView.Nodes["Backgrounds"];
            Backgrounds.ImageIndex = addImage("images/editor/background");
            Backgrounds.SelectedImageIndex = Backgrounds.ImageIndex;

            loadCategory<BackgroundElementNode>(Backgrounds.Nodes, "images/level/backgrounds");

            TreeNode Foregrounds = resourcesView.Nodes["Foregrounds"];
            Foregrounds.ImageIndex = addImage("images/editor/foreground");
            Foregrounds.SelectedImageIndex = Foregrounds.ImageIndex;

            loadCategory<ForegroundElementNode>(Foregrounds.Nodes, "images/level/foregrounds");

            TreeNode Obstacles = resourcesView.Nodes["Level"].Nodes["Obstacles"];
            Obstacles.ImageIndex = addImage("images/editor/obstacle");
            Obstacles.SelectedImageIndex = Obstacles.ImageIndex;

            loadCategory<ObstacleElementNode>(Obstacles.Nodes, "images/level/level/obstacles");

            TreeNode Portalables = resourcesView.Nodes["Level"].Nodes["Obstacles"].Nodes["Portalables"];
            Portalables.ImageIndex = addImage("images/editor/obstacle");
            Portalables.SelectedImageIndex = Portalables.ImageIndex;

            loadCategory<PortalableElementNode>(Portalables.Nodes, "images/level/level/obstacles/portalables");

            TreeNode Burnables = resourcesView.Nodes["Level"].Nodes["Obstacles"].Nodes["Burnables"];
            Burnables.ImageIndex = addImage("images/editor/obstacle");
            Burnables.SelectedImageIndex = Burnables.ImageIndex;

            loadCategory<BurnableElementNode>(Burnables.Nodes, "images/level/level/obstacles/burnables");

            TreeNode Scenery = resourcesView.Nodes["Level"].Nodes["Scenery"];
            Scenery.ImageIndex = addImage("images/editor/scenery");
            Scenery.SelectedImageIndex = Scenery.ImageIndex;

            loadCategory<SceneryElementNode>(Scenery.Nodes, "images/level/level/scenery");

            //resourcesView.ExpandAll();

            resourcesView.SelectedNode = Obstacles.Nodes[2];
            currentNode = (LevelElementNode)Obstacles.Nodes[2];
            currentNode.Checked = true;
        }

        private void loadCategory<T>(TreeNodeCollection nodes, string directory) where T : LevelElementNode, new()
        {
            DirectoryInfo dir = new DirectoryInfo(Content.RootDirectory + "\\" + directory);

            FileInfo[] files = dir.GetFiles("*.*");
            foreach (FileInfo file in files)
            {
                string fileName = directory + "\\" + Path.GetFileNameWithoutExtension(file.Name);
                T levelElementNode = new T();
                levelElementNode.Initialize(this, fileName);
                nodes.Add(levelElementNode);
            }
        }

        private void selectItem(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Node.GetNodeCount(true) == 0)
            {
                currentNode = (LevelElementNode)e.Node;

                if (currentNode is BackgroundElementNode)
                    displayBackgroundCheckbox.Checked = true;

                else if (currentNode is ObstacleElementNode)
                    displayObstaclesCheckbox.Checked = true;

                else if (currentNode is ForegroundElementNode)
                    displayForegroundCheckbox.Checked = true;
            }
        }

        public Texture2D getCurrentTexture()
        {
            return currentNode.getTexture();
        }

        public LevelElement getNewElement(Vector2 position)
        {
            return currentNode.getNewElement(editorMode.getLevel(), position);
        }

        public bool displayBackground()
        {
            return displayBackgroundCheckbox.Checked;
        }

        public bool displayObstacles()
        {
            return displayObstaclesCheckbox.Checked;
        }

        public bool displayForeground()
        {
            return displayForegroundCheckbox.Checked;
        }

        private void OnClose(object sender, FormClosedEventArgs e)
        {
            Environment.Exit(0);
        }

        private void resourcesView_AfterSelect(object sender, TreeViewEventArgs e)
        {

        }

        private void backUpLevel(string name)
        {
            if (File.Exists(tgsDir + "\\" + name))
            {
                int i = 1;
                while (File.Exists(backUpDir + "\\" + name + "." + i))
                    i++;

                File.Move(tgsDir + "\\" + name, backUpDir + "\\" + name + "." + i);
            }
        }

        private void newButton_Click(object sender, EventArgs e)
        {
            Level level = new Level(Content);
            level.paginateElements(new List<LevelElement>());
            editorMode.setLevel(level);
            saveTextBox.Text = "level.lvl";
        }

        private void openButton_Click(object sender, EventArgs e)
        {
            //RawLevel rl = Content.Load<RawLevel>("levels/level");
            string levelName = (string)openComboBox.SelectedItem;
            if (levelName != null && levelName != "")
            {
                saveTextBox.Text = levelName;
                RawLevel rl = RawLevel.fromBytes(File.ReadAllBytes(tgsDir + "\\" + levelName));
                editorMode.setLevel(editor.LevelConverter.toLevel(rl, Content));
            }
        }

        private void saveButton_Click(object sender, EventArgs e)
        {
            string levelName = saveTextBox.Text.Trim();
            if (levelName != null && levelName != "")
            {
                if (!levelName.EndsWith(".lvl"))
                {
                    levelName += ".lvl";
                    saveTextBox.Text = levelName;
                }
                RawLevel rl = LevelConverter.fromLevel(editorMode.getLevel());
                backUpLevel(levelName);
                File.WriteAllBytes(tgsDir + "\\" + levelName, rl.toBytes());
                loadLevelList();
            }
        }

        private void deleteMarkButton_Click(object sender, EventArgs e)
        {
            string markName = deleteMarkTextBox.Text;
            deleteMarkTextBox.Text = "";
            editorMode.getLevel().deleteMarks(markName);
        }

        private void loadLevelList()
        {
            openComboBox.Items.Clear();
            DirectoryInfo dir = new DirectoryInfo(tgsDir);

            FileInfo[] files = dir.GetFiles("*.lvl");
            foreach (FileInfo file in files)
                openComboBox.Items.Add(file.Name);
        }

        private void editorTabs_selected(object sender, TabControlEventArgs e)
        {
            if (editorTabs.SelectedTab.Name == "loadAndSaveTab")
                loadLevelList();
        }

    }
}
